#include <mutex>
#include <iostream>
#include <memory>

//控制块
class RefCounter 
{
private:
    long count;
public:
    RefCounter(long val) : count(val) {};
    void add_ref() { ++count; }
    const long reduce_ref() { return --count; }
    long get_use_count() const noexcept { return count; }
};

template<typename T>
class Shared_ptr 
{
private:
    T* _ptr;
    RefCounter* _count;
    std::mutex* _mutex;

public:
    Shared_ptr() noexcept = default;

    explicit Shared_ptr(T* ptr = nullptr) : _ptr(ptr) 
    {
        if (!_ptr) return;

        _count = new RefCounter(1);
        _mutex = new std::mutex{};
    }

    Shared_ptr(const Shared_ptr& ptr) noexcept : _ptr(ptr._ptr), _count(ptr._count), _mutex(ptr._mutex) {
        if (!_ptr)  return;
        _count->add_ref();
    }

    ~Shared_ptr()
    {
        if (0 == _count->reduce_ref()) 
        {
            delete this->_ptr;
            delete this->_count;
        }
    }

    SmartPointer& operator=(const SmartPointer& ptr) 
    {
        if (_ptr == ptr._ptr) {
            return *this;
        }

        if (this->_ptr) 
        {
            if (0 == _count->reduce_ref()) 
            {
                delete this->_ptr;
                delete this->_count;
            }
        }

        this->_ptr = ptr._ptr;
        this->_count = ptr._count;
        _count->add_ref();
        return *this;
    }

    T& operator*() 
    {
        assert(this->_ptr == nullptr);
        return *(this->_ptr);

    }

    T* operator->() {
        assert(this->_ptr == nullptr);
        return this->_ptr;
    }

    size_t use_count() {
        return _count->get_use_count();
    }

};

